#include "MicroBit.h"
#include "audio.h"
#include "neopixel_lib.h"

extern MicroBit uBit;
MicroBitUARTService *uart;

const char *const happy_emoji = "\
    000,255,000,255,000\n\
    000,000,000,000,000\n\
    255,000,000,000,255\n\
    000,255,255,255,000\n\
    000,000,000,000,000\n";

const char *const sad_emoji = "\
    000,255,000,255,000\n\
    000,000,000,000,000\n\
    000,000,000,000,000\n\
    000,255,255,255,000\n\
    255,000,000,000,255\n";

const char *const radio_emoji = "\
    255,255,255,000,000\n\
    000,000,000,255,000\n\
    255,255,000,000,255\n\
    000,000,255,000,255\n\
    255,000,255,000,255\n";

MicroBitImage smile(happy_emoji);
MicroBitImage sad(sad_emoji);
MicroBitImage radio(radio_emoji);

ManagedString eom(":");

// we use events abd the 'connected' variable to keep track of the status of the Bluetooth
// connection
static void onConnected(MicroBitEvent)
{
    uBit.display.print(smile);
    bleConnectedPitch();
}

static void onDisconnected(MicroBitEvent)
{
    uBit.display.print(sad);
    bleDisconnectedPitch();
}

static void onDelim(MicroBitEvent)
{

    ManagedString r = uart->readUntil(eom);
    uart->send(r);
    if (r == "np_l8")
    {
        neopixel_set_length(8);
    }
    if (r == "np_l30")
    {
        neopixel_set_length(30);
    }
    if(r == "np_r") {
        neopixel_set_red();
    }
    if (r == "np_g")
    {
        neopixel_set_green();
    }
    if (r == "np_b")
    {
        neopixel_set_blue();
    }
}

void ble_test()
{
    // Configuration Tips
    //
    // An example codal.json is provided in the root directory: codal.ble.json
    // Rename codal.ble.json to codal.json to use this BLE sample
    //
    // codal.json contains various Bluetooth related properties some of which are explained here:
    //
    // "DEVICE_BLE": 1                     Determines whether BLE is enabled
    // "MICROBIT_BLE_ENABLED" : 1          Determines whether BLE is enabled
    // "MICROBIT_BLE_PAIRING_MODE": 1      Determines whether Pairing Mode is enabled
    // "MICROBIT_BLE_DFU_SERVICE": 1       Determines whether the Nordic DFU Service is enabled
    // "MICROBIT_BLE_DEVICE_INFORMATION_SERVICE": 1 Determines whether the DIS is enabled
    // "MICROBIT_BLE_EVENT_SERVICE" : 1,   Determines whether the Event Service is enabled
    // "MICROBIT_BLE_PARTIAL_FLASHING" : 0 Determines whether Partial Flashing is enabled (Needs
    // MakeCode/Python) "MICROBIT_BLE_SECURITY_LEVEL": "SECURITY_MODE_ENCRYPTION_WITH_MITM"
    // Determines security mode
    //
    // Options for MICROBIT_BLE_SECURITY_LEVEL are:
    // SECURITY_MODE_ENCRYPTION_WITH_MITM, enables pairing with a passcode
    // SECURITY_MODE_ENCRYPTION_NO_MITM, enables pairing without a passcode
    // SECURITY_MODE_ENCRYPTION_OPEN_LINK, pairing is not required
    //

    uBit.messageBus.listen(MICROBIT_ID_BLE, MICROBIT_BLE_EVT_CONNECTED, onConnected);
    uBit.messageBus.listen(MICROBIT_ID_BLE, MICROBIT_BLE_EVT_DISCONNECTED, onDisconnected);

    uBit.messageBus.listen(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_DELIM_MATCH, onDelim);

    new MicroBitAccelerometerService(*uBit.ble, uBit.accelerometer);
    new MicroBitButtonService(*uBit.ble);
    new MicroBitIOPinService(*uBit.ble, uBit.io);
    new MicroBitLEDService(*uBit.ble, uBit.display);
    new MicroBitMagnetometerService(*uBit.ble, uBit.compass);
    new MicroBitTemperatureService(*uBit.ble, uBit.thermometer);

    uart = new MicroBitUARTService(*uBit.ble, 32, 32);
    uart->eventOn(eom);

    // A cunning code to indicate during start-up the particular Bluetooth configuration in the
    // build
    //
    // SERVICE CODES
    // A: Accelerometer Service
    // B: Button Service
    // D: Device Information Service
    // E: Event Service
    // F: DFU Service
    // I: IO Pin Service
    // L: LED Service
    // M: Magnetometer Service
    // T: Temperature Service
    // U: UART Service
    //

    // P: PASSKEY
    // J: Just Works
    // N: No Pairing Required

    // Services/Pairing Config/Power Level
    uBit.display.print(radio);

    // if ( !uBit.compass.isCalibrated())
    //     uBit.compass.calibrate();

    // If main exits, there may still be other fibers running or registered event handlers etc.
    // Simply release this fiber, which will mean we enter the scheduler. Worse case, we then
    // sit in the idle task forever, in a power efficient sleep.
    release_fiber();
}